<?php
/**
 * 1. Redis的数据是共享的
　　如果将用户信息存储在web服务的本地缓存，则每个web服务都会缓存一份，当用户修改昵称时，需要通知其它web服务更新用户缓存。
　　如果将用户信息存储在Redis，则只有一份缓存，所有的web访问的都是同一份缓存，当用户修改昵称时，所有web服务都能同时访问到最新的缓存。
　　比如在phpok.me中 set('age',99) 在code.me中 get('age') 是可以获取到age=99的
    2. Redis是单线程的
　　由于Redis的性能瓶颈在于内存读写速度，而不是CPU，设计者将Redis设计成了单线程模式，其所有操作都是原子性的，避免了多线程带来的复杂性。
    关于redis的应用场景
 *  1.可以做计数器
 * string类型的incr和decr命令的作用是将key中储存的数字值加一/减一，这两个操作具有原子性，总能安全地进行加减操作，因此可以用string类型进行计数，如微博的评论数、点赞数、分享数，抖音作品的收藏数，京东商品的销售量、评价数等。
 *  2.可以做分布式锁，比如执行计划任务，或则同时操作时，可以使用setnx 来判断一个键值是否存在，如果存在不执行，则返回0，不过不存在执行 并返回1，即可避免两个操作同时执行，起到“锁”的作用。
 *  3.存储对象，比如json存入string中，用来保存用户信息等。
 */
namespace app\redis\controller;


use think\App;
use think\Controller;
use think\Request;

class String extends Controller
{
    private $redis;

    public function __construct()
    {
        parent::__construct();
        $this->redis =  new \Redis();
        $this->redis->connect('127.0.0.1',6379);
    }

    public function set(Request $request)
    {
        $key = $request->param('key');
        $val = $request->param('val');
        $res = $this->redis->set($key,$val,200);
        if($res){
            return "键值".$key.'已经被赋值'.$val.'过期时间为200秒';
        } else {
            return '赋值失败';
        }
    }

    public function set2(){
        $student = array(
            'name'=>'张三',
            'age'=>16,
            'sex'=>'男',
            'num'=>36,
        );
        $json = json_encode($student);
        $this->redis->set('student',$json);
        $res = $this->redis->get('student');
        return $res;
    }

    //对于已经存在的key，不会改变key的值，如果有没有则设置
    public function setnx()
    {
        $res = $this->redis->setnx('name','zhangsan');
        if($res){
            return '赋值成功';
        } else {
            return '已存在忽略';
        }
    }

    // 和set相似，但设置过期时间只能是秒
    public function setex()
    {
        $res = $this->redis->setex('name','15','xiaoli');
        if($res){
            return '赋值成功';
        } else {
            return '已存在忽略';
        }
    }

    // setex，但设置过期时间可以是毫秒
    public function psetex()
    {
        $res = $this->redis->psetex('name','1000','wangce'); //1000毫秒是一秒
        if($res){
            return '赋值成功';
        } else {
            return '已存在忽略';
        }
    }

    public function get(Request $request)
    {
        $key = $request->param('key');
        $res = $this->redis->get($key);
        if($res){
            return $res;
        } else {
            return "当前key的赋值已过期";
        }
    }

    // 先获取之前的key值后改变key的值
    public function getset()
    {
        $res = $this->redis->getSet('name','laoyang');
        echo '原来的值为'.$res;
        $update = $this->redis->get('name');
        echo '现在的值为'.$update;
    }

    public function strlen()
    {
        $res = $this->redis->strlen('name');
        return $res;
    }

    // 在尾部追加字符，但是返回的是增加后的字符长度
    public function append()
    {
        $res = $this->redis->append('name',' - nihao');
        return $this->redis->get('name');
        return $res;
    }

    //用指定的字符串覆盖给定 key 所储存的字符串值 ，例如 kangkai 用mimi来覆盖 可以改成kangmimi
    public function setrange()
    {
        $res = $this->redis->setRange('name','4','mimi');
        return $this->redis->get('name');
        return $res;
    }

    //返回键 key 储存的字符串值的指定部分 ，kangkai 返回 angk
    public function getrange()
    {
        $res = $this->redis->getRange('name','1','5');
        return $res;
    }

    // 会在int型key值+1，可设置添加的值
    public function incr()
    {
        $res = $this->redis->incr('age');
        return $res;
    }

    public function incrby()
    {
        $res = $this->redis->incrBy('age','15'); //这里设置15.5是没有用的只会按照15添加
        return $res;
    }

    // 添加的值可以说浮点型
    public function incrbyfloat()
    {
        $res = $this->redis->incrByFloat('age','6.66');
        return $res;
    }

    // 减一
    public function decr()
    {
        $res = $this->redis->decr('age');
        return $res;
    }

    public function decrby()
    {
        $res = $this->redis->decrBy('age','13');
        return $res;
    }

    //多键值同时赋值
    public function mset()
    {
        $res = $this->redis->mset(array('name'=>'kangkai','age'=>99,'sex'=>'man'));
        return $this->redis->get('name');
    }

    // 同事设置多个键值，但当有一个键值已存在时，所有到操作全部失败，原子性。
    public function msetex()
    {
        $res = $this->redis->msetnx(array('name'=>'kangkai','age'=>99,'sex'=>'man'));
        if($res){
            return '所有键值都设置成功';
        }else{
            return '设置失败';
        }
    }

    // 同时获取多个键的值
    public function mget()
    {
        $res = $this->redis->mget(array('name','age','sex'));
        dump($res);
    }

}